home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 2
/
Nebula Two.iso
/
SourceCode
/
GameKit
/
gamekit-1
/
PreferencesBrain.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
18KB
|
563 lines
/* Generated by Interface Builder */
#import <daymisckit/daymisckit.h>
#import <gamekit/gamekit.h>
#import <stdio.h>
#import <stdlib.h> /* malloc */
BOOL getBOOLPreference(const char *name, BOOL def)
{
const char *tmpstr = NXGetDefaultValue ([NXApp appName], name);
int temp = def;
if (tmpstr) sscanf(tmpstr, "%d", &temp);
if (temp) return YES;
return NO;
}
int getIntPreference(const char *name, int min, int max, int def)
{
int tempInt;
const char *tmpstr = NXGetDefaultValue ([NXApp appName], name);
if (!tmpstr) return def;
else {
sscanf(tmpstr, "%d", &tempInt);
if (tempInt < min) return min;
if (tempInt > max) return max;
}
return tempInt;
}
const char *getStringPreference(const char *name, const char *def)
{
const char *tmpstr = NXGetDefaultValue ([NXApp appName], name);
if (tmpstr == NULL) return def;
return tmpstr;
}
void putIntPreference(const char *name, int value)
{
char str[16];
sprintf(str, "%d", value);
NXWriteDefault ([NXApp appName], name, str);
}
void putBOOLPreference(const char *name, BOOL value)
{
char str[16];
int tempInt = 0;
if (value) tempInt = 1;
sprintf(str, "%d", tempInt);
NXWriteDefault ([NXApp appName], name, str);
}
void putStringPreference(const char *name, const char *value)
{
NXWriteDefault ([NXApp appName], name, value);
}
@implementation PreferencesBrain
static char *defaultServer = "*"; // very slow -- subclass should override!
- init // designated initializer sets up game variables
{ // to sensible values.
int i;
[super init];
for (i=0; i<MAXKEYS; i++) { // get space to store default keypresses in
keys[i] = malloc(8);
defkey[i] = malloc(8);
}
numKeys = 5;
strcpy(defkey[0], "a");
strcpy(defkey[1], "z");
strcpy(defkey[2], "l");
strcpy(defkey[3], ";");
strcpy(defkey[4], " ");
defaultPlayerName = [[DAYString alloc] init];
version = malloc(8);
serverName = NXCopyStringBufferFromZone(defaultServer, [self zone]);
firstLoad = YES;
return self;
}
- appDidInit:sender // forwarded by GameBrain
{ // Do all our basic init here
if (!gameBrain) gameBrain = [NXApp delegate];
if (!info) info = [gameBrain infoController];
if (!scorePlayer) scorePlayer = [gameBrain scorePlayer];
if (!soundPlayer) soundPlayer = [gameBrain soundPlayer];
if (!highScoreTable)
highScoreTable = [gameBrain highScoreController];
if (!strings) strings = [gameBrain mainStrings];
if (!gameScreen) gameScreen = [gameBrain gameScreen];
[self readDefaults:self];
[gameScreen getPreferences];
return self;
}
// methods to get at instance variables
- (int)startLevel { return level; } // returns starting level
- (int)speed { return speed; }
- (BOOL)border { return border; } // return YES if gray border is on
- (BOOL)effects { return effects; }
- (BOOL)music { return music; }
- (BOOL)alert { return alert; }
- (BOOL)autoUnPause { return autoUnPause; }
- (BOOL)autoStart { return autoStart; }
- (BOOL)demoSound { return demoSound; }
- (BOOL)useServer { return useServer; }
- setAlert:(BOOL)al { alert = al; return self; }
- setAutoUnPause:(BOOL)al { autoUnPause = al; return self; }
- setAutoStart:(BOOL)al { autoStart = al; return self; }
- (const char *)serverName { return serverName; }
- setNumKeys:(int)num { numKeys = num; return self; }
- readDefaults:sender // get preferences from defaults database
{
char *tmpstr = malloc(16);
int i;
if (serverName) free(serverName);
useServer = getBOOLPreference("UseServer", NO);
effects = getBOOLPreference("SoundOn", YES);
alert = getBOOLPreference("Alerts", YES);
autoUnPause = getBOOLPreference("AutoUnPause", YES);
autoStart = getBOOLPreference("AutoStart", YES);
border = getBOOLPreference("Border", YES);
demoSound = getBOOLPreference("DemoSound", YES);
music = getBOOLPreference("MusicOn", YES);
level = getIntPreference("StartLevel", 1, 20, 1);
speed = getIntPreference("GameSpeed", 0, 2, 1);
serverName = NXCopyStringBufferFromZone(
getStringPreference("ServerName", defaultServer), [self zone]);
strcpy(version, getStringPreference("Version", "0.0"));
[self setDefaultPlayerName:getStringPreference(
"PlayerName", [NXApp userRealName])];
for (i=0; i < numKeys; i++) {
sprintf(tmpstr, "Key%d", i);
strcpy(keys[i], getStringPreference(tmpstr, defkey[i]));
[gameScreen setKey:i val:keys[i][0]];
}
[gameScreen getPreferences];
[highScoreTable setServerHost:serverName];
if (useServer) [highScoreTable setLocalScores:NO];
else [highScoreTable setLocalScores:YES];
// if couldn't locate the server, go local.
if (useServer && [highScoreTable localScores]) useServer = NO;
free(tmpstr);
[soundPlayer turnOn:effects];
return self;
}
- writeDefaults:sender // save preferences in defaults database
{
char str[32]; int i;
putBOOLPreference ("Border", border);
putBOOLPreference ("Alerts", alert);
putBOOLPreference ("AutoStart", autoStart);
putBOOLPreference ("AutoUnPause", autoUnPause);
putBOOLPreference ("DemoSound", demoSound);
putBOOLPreference ("MusicOn", music);
putBOOLPreference ("SoundOn", effects);
putBOOLPreference ("UseServer", useServer);
putIntPreference ("GameSpeed", speed);
putIntPreference ("StartLevel", level);
putStringPreference ("Version", version);
putStringPreference ("ServerName", serverName);
putStringPreference ("PlayerName", [defaultPlayerName stringValue]);
for (i=0; i<numKeys; i++) { // ***** it would be better to make a single
// string for all the keys; in the future I might make this adjustment.
// This method leaves quite a few defaults...
sprintf(str, "Key%d", i);
putStringPreference(str, keys[i]);
}
return self;
}
- (BOOL)firstTimeCheck // first time running this version?
{
if (!version || ![info versionString]) return NO; // if NULL, then this
// mechanism is disabled, so it's NEVER the first time running...
if (strcmp(version, [info versionString])) { // first time if !=
strcpy(version, [info versionString]);
return YES; // when the Prefs are saved (exit, etc.) the version
// # will be stored in defaults and then next time we'll return a NO
}
return NO;
}
- revert:sender // return to default values
{
int tempInt;
speed = 1; effects = YES; alert = YES;
autoUnPause = YES; autoStart = YES; border = YES;
demoSound = YES; music = YES; useServer = NO;
if (serverName) free(serverName);
serverName = NXCopyStringBufferFromZone(defaultServer, [self zone]);
if (![highScoreTable localScores]) [highScoreTable closeServers];
[highScoreTable setServerHost:serverName];
[gameScreen revertBackground:sender];
for (tempInt=0; tempInt<numKeys; tempInt++) {
strcpy(keys[tempInt], defkey[tempInt]);
}
// I'm not reverting defaultPlayerName; doesn't seem necessary
for (tempInt=0; tempInt<4; tempInt++)
[gameScreen setKey:tempInt val:keys[tempInt][0]];
[gameScreen getPreferences]; // make sure that the gameScreen is aware
return [self preferences:self]; // update the panel
}
- takeKey:sender // used by below (keyChange) to get new keys
{ // This is klunky; there's a better way to fill up the matrix; I'll
// fix it eventually ***** (See how the GKHighScorePanel does it; it's
// much cleaner than this.)
strcpy(keys[[sender tag]],[sender stringValue]); // store internally
[gameScreen setKey:[sender tag] val:keys[[sender tag]][0]]; // send to view
return self;
}
- (char)keyVal:(int)keyIndex // returns default key for action (0-4)
{ return keys[keyIndex][0]; }
- keyChange:sender // accept changes in keys
{
[keyMatrix sendAction:@selector(takeKey:) to:self forAllCells:YES];
// ***** I should check here to be sure that the new keys don't
// conflict with each other or with the 'p' and 'n' keys...
return self;
}
- changeLevel:sender
{
level = [sender intValue];
if (sender != levelSlider) [levelSlider setIntValue:level];
else [levelText setIntValue:level];
return self;
}
- speedChange:sender // accept changes in speed
{
speed = [sender selectedTag];
return self;
}
- findKeyFor:sender // used by below to set keys in pref. matrix
{
[sender setStringValue:keys[[sender tag]]];
return self;
}
- setUpViews
{ // here is where we hook up the views to be switched around in the panel
// you should override this to add extra panes besides the three basic
// ones expected here; you can use Columns as an example of how you
// would go about doing this.
[inspectorBox getFrame:&inspectFrame];
[viewPlayer getFrame:&view[0]];
[viewScreen getFrame:&view[1]];
[viewSound getFrame:&view[2]];
ViewsList = [[List alloc] init];
thePopUpList = [thePopUpListButton target];
[thePopUpList setTarget:self];
[thePopUpList setAction:@selector(toggleInspectorPanels:)];
[thePopUpList removeItemAt:0];
[thePopUpList removeItemAt:0];
[thePopUpList removeItemAt:0];
[[[[self
addView:viewPlayer withName:[strings valueForStringKey:"Player"]]
addView:viewScreen withName:[strings valueForStringKey:"Screen"]]
addView:viewSound withName:[strings valueForStringKey:"Sound" ]]
show:[strings valueForStringKey:"Player"]];
[preferencesPanel orderFront:self];
[inspectorBox display];
return self;
}
- preferences:sender // sets controls on pref panel & brings it up
{
[self preferencesPanel]; // be sure panel is loaded; throw away return val.
if (firstLoad) {
[self setUpViews];
[preferencesPanel orderFront:self];
[inspectorBox display];
firstLoad = NO;
}
[self refresh];
[[self preferencesPanel] orderFront:self];
return self;
}
- refresh // refresh all controls -- set them to display the current state
{
[speedButtons selectCellWithTag:speed];
[musicButtons selectCellWithTag:music];
[effectButtons selectCellWithTag:effects];
[levelText setIntValue:level];
[levelSlider setIntValue:level];
[alertSwitch setState:alert];
[borderSwitch setState:border];
[serverButton setState:useServer];
[serverText setStringValue:serverName];
[autoStartSwitch setState:autoStart];
[autoUnPauseSwitch setState:autoUnPause];
[demoSwitch setState:demoSound];
[keyMatrix sendAction:@selector(findKeyFor:) to:self forAllCells:YES];
return self;
}
//
// Methods to handle inspectors and swapping views around...
// (Very much adapted from NewInspector.m)
//
- free
{
[ViewsList free];
[preferencesPanel orderOut:self];
return [super free];
}
- addView:(id)aView withName:(const char *)name
{
[ViewsList addObject:aView];
[thePopUpList addItem:name];
return self;
}
- show:(const char *)name
{
[self turnOnView:[thePopUpList indexOfItem:name]];
[thePopUpListButton setTitle:name];
return self;
}
- toggleInspectorPanels:sender
{ // from pop-up list; we display the appropriate view.
return [self turnOnView:[sender selectedRow]];
}
- turnOnView:(int)i
{
NXRect newFrame;
[preferencesPanel disableFlushWindow];
// get the right view
[inspectorBox setContentView:[ViewsList objectAt:i]];
// resize and move to the right place
newFrame.size.width = view[i].size.width;
newFrame.size.height = view[i].size.height;
newFrame.origin.x = inspectFrame.origin.x +
(inspectFrame.size.width - view[i].size.width)/2;
newFrame.origin.y = inspectFrame.origin.y +
(inspectFrame.size.height - view[i].size.height)/2;
[inspectorBox setFrameFromContentFrame:&newFrame];
// erase junk around it -- this wouldn't be necessary if I
// properly added/removed the Views from the respective hierarchies.
// sometime I'll get around to fixing this.
newFrame.size.width = view[i].size.width;
newFrame.size.height = view[i].size.height;
newFrame.origin.x = inspectFrame.origin.x +
(inspectFrame.size.width - view[i].size.width)/2;
newFrame.origin.y = inspectFrame.origin.y +
(inspectFrame.size.height - view[i].size.height)/2;
[grayView aroundFrame:&newFrame :inspectFrame.origin.y];
// finally, display the new view
[inspectorBox display];
[self refresh];
[preferencesPanel reenableFlushWindow];
[preferencesPanel flushWindowIfNeeded];
return self;
}
- preferencesPanel // return the preferencesPanel, load it if needed.
{
if( !preferencesPanel) {
[NXApp loadNibSection:"PreferencesPanel.nib" owner:self withNames:NO];
[preferencesPanel setFrameUsingName:"Prefs"];
[preferencesPanel setFrameAutosaveName:"Prefs"];
}
return preferencesPanel;
}
- musicChange:sender // turn music on/off
{
music = [[sender selectedCell] tag];
// music runs independently, so we just turn it on or off at the
// appropriate times. *****Maybe I should have the score playback
// pause when you pause a game; right now it doesn't.
#ifdef GK_USE_MUSICKIT
if ((music) && ([gameScreen gameState] != GAMEOVER))
[scorePlayer play:self];
else [scorePlayer stop:self];
#endif
return self;
}
- setScore:sender
{ // sent by "Set Score File..." button; we forward to the ScorePlayer
#ifdef GK_USE_MUSICKIT
[scorePlayer selectFile:sender];
#endif
return self;
}
- effectsChange:sender // turn sound effects on/off
{
effects = [[sender selectedCell] tag];
[soundPlayer turnOn:effects];
return self;
}
- setDefaultPlayerName:(const char *)aString // change default player name
{
if (aString) [defaultPlayerName setStringValue:aString];
else [defaultPlayerName setStringValue:"Mystery Player"];
return self;
}
- (const char *)defaultPlayerName // return ptr to defaultPlayerName string
{
return [defaultPlayerName stringValue];
}
- alertChange:sender
{
alert = NO;
if ([sender state]) alert = YES;
return self;
}
- unPauseChange:sender
{
autoUnPause = NO;
if ([sender state]) autoUnPause = YES;
return self;
}
- autoStartChange:sender
{
autoStart = NO;
if ([sender state]) autoStart = YES;
return self;
}
- demoSoundChange:sender // New turn off sound only in demo
{
demoSound = NO;
if ([sender state]) demoSound = YES;
return self;
}
- setBack:sender // set the background image
{ // forward the message to the game screen
return [gameScreen changeBackground:sender];
}
- revertBack:sender // revert to default background image
{ // forward the message to the game screen
return [gameScreen revertBackground:sender];
}
- (BOOL)borderOn { return border; }
- setBorder:(BOOL)newBord
{ // turn gray border on/off
if (border == newBord) return self;
border = newBord;
[gameScreen changeBorder:border]; // inform the GameView to adjust things.
return self;
}
- borderChange:sender
{ // turn gray border on/off -- sent by control on the panel
// this is a cover for the above method
return [self setBorder:[sender state]];
}
- setUseServer:(BOOL)useIt
{ // This allows the high score controlling object to turn things off
// if it can't connect or it loses the connection to the server
useServer = useIt;
[serverButton setState:useIt];
return [self refresh];
}
- changeServer:sender
{ // The main if block handles the button/check box, while the else
// block handles changing the server name (and also automatically
// checks the server box)
if (sender != serverText) { // user changed the button state
BOOL newUse = NO;
// get the state of the check box
if ([serverButton state]) newUse = YES;
if (useServer != newUse) { // turn local on/off
// attempt to connect to the servers if we aren't already
// note that this call only will happen if we're going local
// to network; if going the other way, we're already connected
// so we pass through...
if (![highScoreTable connected]) [highScoreTable connectToServers];
// before finishing, make sure there were no problems connecting;
// we can't assume all is OK. (The -connected handles that; the
// 0 is in the case of going to a local table...)
useServer = (newUse ? [highScoreTable connected] : 0);
[highScoreTable setLocalScores:!useServer];
}
} else {
// check to see if the name is changing
if (strcmp(serverName, [serverText stringValue])) {
// make note of the new name (it has changed)
if (serverName) free(serverName);
serverName = NXCopyStringBufferFromZone([serverText stringValue],
[self zone]);
[highScoreTable setServerHost:serverName];
// close current servers if already connected
// because we need to switch to a different server
if ([highScoreTable connected]) [highScoreTable closeServers];
}
// force us to use the server (i.e. return in server field will cause
// the check box to be checked automatically, enabling the server.)
useServer = YES;
[serverButton setState:useServer];
if (![highScoreTable connected]) [highScoreTable connectToServers];
// refresh the high score panel amongst other things.
[highScoreTable setLocalScores:![highScoreTable connected]];
}
// Note that if we couldn't locate the server, we go local.
// (The HighScoreController did that automatically for us above.)
// Finally, refresh the prefs panel to reflect any changes of internal
// state, in particular the state of the check box, which may have
// changed due to what happened above. (No connection, etc.)
[self refresh];
return self;
}
// if the Prefs are "unfair" then a game cannot be saved on a network server.
// it is up to you to add methods that set unfair when the prefs become
// unfair. Also, in -startingGame, you should set unfair if any prefs are
// unfair to begin with. As it stands here, any game is fair... Note that
// the only way to clear the unfair variable is by starting a new game with
// fair prefs; once a pref is made unfair, the game is unfair even if you
// change it back.
- (BOOL)unfair { return unfair; }
- setUnfair { unfair = YES; return self; }
- startingGame // reset the unfair variable
{
unfair = NO;
return self;
}
@end